home *** CD-ROM | disk | FTP | other *** search
/ Network PC / Network PC.iso / amiga utilities / communication / bbs / hydrabbsa8 / source / src.lha / node / nodelibrary / HBBSNode.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-09-08  |  32.5 KB  |  1,153 lines

  1. #define HBBSNODELIB
  2. #define MAIN
  3.  
  4. #include <ctype.h>
  5. #include <time.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9.  
  10. #include <exec/exec.h>
  11. #include <exec/types.h>
  12.  
  13. #include <dos/dos.h>
  14. #include <dos/dostags.h>
  15.  
  16. #include <libraries/reqtools.h>
  17.  
  18. #include <intuition/intuition.h>
  19.  
  20. #include <devices/console.h>
  21. #include <devices/conunit.h>
  22.  
  23. #include <devices/serial.h>
  24. #include <hardware/cia.h>
  25.  
  26. #include <graphics/gfxbase.h>
  27. #include <graphics/scale.h>
  28.  
  29.  
  30. #include <clib/exec_protos.h>
  31. #include <clib/dos_protos.h>
  32. #include <clib/alib_protos.h>
  33. #include <clib/reqtools_protos.h>
  34. #include <clib/graphics_protos.h>
  35.  
  36. #include <pragmas/exec_pragmas.h>
  37. #include <pragmas/graphics_pragmas.h>
  38. #include <pragmas/dos_pragmas.h>
  39. #include <pragmas/reqtools.h>
  40.  
  41.  
  42. #include "//common/types.h"
  43. #include "//common/errors.h"
  44. #include "//common/defines.h"
  45. #include "//common/structures.h"
  46. #include "//common/strings.h"
  47. #include "//common/files.h"
  48. #include "//common/access.h"
  49.  
  50. #include "//library/hbbscommon_protos.h"
  51. #include "//library/hbbscommon_pragmas.h"
  52.  
  53. #define ClrSignal(s)  SetSignal(0,s)
  54.  
  55.  
  56. // needed libs..
  57.  
  58. struct DosLibrary *DOSBase=NULL;
  59. struct GfxBase *GfxBase=NULL;
  60. struct ExecBase *SysBase=NULL;
  61. struct ReqToolsBase *ReqToolsBase=NULL;
  62. struct Library *HBBSCommonBase=NULL;
  63.  
  64. struct BBSGlobalData *BBSGlobal=NULL;
  65. struct NodeData *N_ND=NULL;
  66.  
  67. struct DoorData C_DOOR; // current door (if active of course!)
  68.  
  69. V_BOOL DoorOK=FALSE;
  70.  
  71. void DoorStatus(V_BIGNUM status)
  72. {
  73.   struct DoorActivityMsg *DMsg;
  74.  
  75.   // memory will be free'd by NODE program (if node is alive of course!)
  76.   if (DMsg=(struct DoorActivityMsg *)AllocVec(sizeof(struct DoorActivityMsg),MEMF_PUBLIC))
  77.   {
  78.     DMsg->message.mn_Node.ln_Type = NT_MESSAGE;
  79.     DMsg->message.mn_ReplyPort=NULL;  // must set to null!
  80.     DMsg->message.mn_Length=sizeof(struct DoorActivityMsg);
  81.     DMsg->MsgType=mtype_DOORACTIVITY;
  82.     DMsg->Status=status;
  83.     SendMessage((struct Message*)DMsg,N_ND->PortName);
  84.   }
  85. }
  86.  
  87. BOOL SendStartDoorMsg( void )
  88. {
  89.   struct DoorActivityMsg *DMsg;
  90.   BOOL retval=FALSE;
  91.  
  92.   if (DMsg=AllocVec(sizeof(struct DoorActivityMsg ),MEMF_PUBLIC))
  93.   {
  94.     DMsg->message.mn_Node.ln_Type = NT_MESSAGE;
  95.     DMsg->message.mn_ReplyPort=C_DOOR.ReplyPort;
  96.     DMsg->message.mn_Length=sizeof(struct DoorActivityMsg);
  97.     DMsg->MsgType=mtype_DOORACTIVITY;
  98.     DMsg->Status=1;
  99.     if (SendMessage((struct Message*)DMsg,N_ND->DoorStartPortName)) retval=TRUE;
  100.     FreeVec(DMsg);
  101.   }
  102.   return(retval);
  103. }
  104.  
  105.  
  106. BOOL __asm __saveds LIBHBBS_InitNode(register __d0 int N_NodeNum)
  107. {
  108.   SysBase = *(struct ExecBase **) 4L;
  109.   if (DOSBase = (struct DosLibrary *) OpenLibrary (DOSNAME, 0))
  110.   {
  111.     if (GfxBase = (struct GfxBase *) OpenLibrary (GRAPHICSNAME, 0))
  112.     {
  113.       if (ReqToolsBase = (struct ReqToolsBase *) OpenLibrary (REQTOOLSNAME, REQTOOLSVERSION))
  114.       {
  115.         if (HBBSCommonBase = OpenLibrary("HBBSCommon.library",0))
  116.         {
  117.           if (BBSGlobal=HBBS_GimmeBBS())
  118.           {
  119.             if (N_ND=HBBS_NodeDataPtr(N_NodeNum))
  120.             {
  121.               return(TRUE);
  122.             }
  123.           }
  124.         }
  125.       }
  126.     }
  127.   }
  128.   return(FALSE);
  129. }
  130.  
  131. void __asm __saveds LIBHBBS_CleanUpNode( void )
  132. {
  133.   if (HBBSCommonBase)
  134.   {
  135. //    if (N_ND) HBBS_ResetNodeData(N_ND); // reset node variables
  136.     CloseLibrary (HBBSCommonBase);
  137.   }
  138.   if (ReqToolsBase) CloseLibrary ((struct Library *)ReqToolsBase);
  139.   if (GfxBase) CloseLibrary ((struct Library *) GfxBase);
  140.   if (DOSBase) CloseLibrary ((struct Library *) DOSBase);
  141. }
  142.  
  143. BOOL __asm __saveds LIBHBBS_InitDoor( register __d0 int N_NodeNum, register __a0 char *name)
  144. {
  145.   if (LIBHBBS_InitNode(N_NodeNum))
  146.   {
  147.     C_DOOR.node.ln_Name=name;
  148.  
  149.     sprintf(C_DOOR.DoorPortName,"HBBS_Node%dDoorPort_%d",N_NodeNum,N_ND->DoorsRunning+1); // we increment door number below..
  150.  
  151.     if (C_DOOR.DoorPort=CreatePort(C_DOOR.DoorPortName,0)) // named port
  152.     {
  153.       if (C_DOOR.ReplyPort=CreateMsgPort()) // unnamed port
  154.       {
  155.         // these must be updated at the same time as we don't want another program referencing
  156.         // ActiveDoor AND the door list and it not being correct now do we ? :-)
  157.  
  158.         Forbid();
  159.         N_ND->ActiveDoor=&C_DOOR;
  160.         AddHead(N_ND->DoorList,(struct Node*)&C_DOOR);
  161.         N_ND->DoorsRunning++;
  162.         Permit();
  163.  
  164.         // tell the NODE the door is running OK (if the node does not get a door OK message)
  165.         // within 15 seconds then it timesout! (unlike /X which locks up!!)
  166.  
  167.         if (SendStartDoorMsg())
  168.         {
  169.           DoorStatus(DMSG_DOORSTARTED);
  170.           // set the internal library's flag (used when we close the door down to free mem!
  171.           DoorOK=TRUE;
  172.           return(TRUE);
  173.         }
  174.  
  175.       }
  176.       else DeletePort(C_DOOR.DoorPort);
  177.     }
  178.   }
  179.   return(FALSE);
  180. }
  181.  
  182. void __asm __saveds LIBHBBS_CleanUpDoor( void )
  183. {
  184.   if (DoorOK)
  185.   {
  186.     DeleteMsgPort(C_DOOR.ReplyPort); // unnnamed port
  187.     DeletePort(C_DOOR.DoorPort);     // named port
  188.     Forbid();
  189.     // remove ourself from the doorlist
  190.  
  191.     RemHead(N_ND->DoorList);
  192.  
  193.     N_ND->DoorsRunning--;
  194.  
  195.     // set the active door to the door that called us (if we were spawned by another door)
  196.     // if not, set activedoor to null
  197.  
  198.     if (N_ND->DoorList->lh_Head->ln_Succ) // more doors ?
  199.     {
  200.       N_ND->ActiveDoor=(struct DoorData *)N_ND->DoorList->lh_Head;
  201.     }
  202.     else N_ND->ActiveDoor=NULL;
  203.  
  204.     Permit();
  205.  
  206.  
  207.     // tell the node that we've finished!
  208.     DoorStatus(DMSG_DOORFINISHED);
  209.  
  210.   }
  211.   LIBHBBS_CleanUpNode();
  212. }
  213. void  __asm __saveds LIBConWriteData(register __a0 UBYTE *data,register __d0 ULONG length)
  214. {
  215.   if (N_ND->ConOK && data && length>=0)
  216.   {
  217.     N_ND->ConWrite->io_Command  = CMD_WRITE;
  218.     N_ND->ConWrite->io_Data     = data;
  219.     N_ND->ConWrite->io_Length   = length;
  220.  
  221.     DoIO((struct IORequest *)N_ND->ConWrite);
  222.   }
  223. }
  224.  
  225. void  __asm __saveds LIBConWriteStr(register __a0 UBYTE *data)
  226. {
  227.   if (N_ND->ConOK && data)
  228.   {
  229.     N_ND->ConWrite->io_Command  = CMD_WRITE;
  230.     N_ND->ConWrite->io_Data     = data;
  231.     N_ND->ConWrite->io_Length   = -1;
  232.  
  233.     DoIO((struct IORequest *)N_ND->ConWrite);
  234.   }
  235. }
  236.  
  237. void  __asm __saveds LIBAbortConRead( void )
  238. {
  239.   if (N_ND->ConWaiting)
  240.   {
  241.     if (!CheckIO((struct IORequest*)N_ND->ConRead))
  242.     {
  243.       AbortIO((struct IORequest*)N_ND->ConRead);
  244.       WaitIO((struct IORequest*)N_ND->ConRead);
  245.     }
  246.     N_ND->ConWaiting=FALSE;
  247.   }
  248. }
  249.  
  250. void  __asm __saveds LIBSendConReadData( void )
  251. {
  252.   if (N_ND->ConWaiting) LIBAbortConRead();
  253.   N_ND->ConRead->io_Command  = CMD_READ;
  254.   N_ND->ConRead->io_Data     = (APTR)N_ND->ConBuffer;
  255.   N_ND->ConRead->io_Length   = N_ND->ConBufferLen;
  256.  
  257.   ClrSignal(1L << N_ND->ConRPort->mp_SigBit);
  258.   SendIO((struct IORequest*)N_ND->ConRead);
  259.   N_ND->ConWaiting=TRUE;
  260. }
  261.  
  262. void  __asm __saveds LIBConReadData(register __d0 ULONG Length ) // make DAMN sure that length is NEVER more that the buffer size!
  263. {
  264.   if (N_ND->ConWaiting) LIBAbortConRead();
  265.   N_ND->ConRead->io_Command  = CMD_READ;
  266.   N_ND->ConRead->io_Data     = (APTR)N_ND->ConBuffer;
  267.   N_ND->ConRead->io_Length   = Length;
  268.  
  269.   ClrSignal(1L << N_ND->ConRPort->mp_SigBit);
  270.   SendIO((struct IORequest*)N_ND->ConRead);
  271.   N_ND->ConWaiting=TRUE;
  272. }
  273.  
  274. void  __asm __saveds LIBConWaitData( void )
  275. {
  276.   if (!N_ND->ConWaiting) LIBSendConReadData();
  277.   WaitIO((struct IORequest*)N_ND->ConRead);
  278.   N_ND->ConWaiting=FALSE;
  279.   N_ND->ConBytes=N_ND->ConRead->io_Actual;
  280. }
  281.  
  282. // aborts an iorequest that has been sent
  283.  
  284. void __asm __saveds LIBAbortSerRead( void )
  285. {
  286.   if (N_ND->SerWaiting)
  287.   {
  288.     if (!CheckIO((struct IORequest*)N_ND->SerRead))
  289.     {
  290.       AbortIO((struct IORequest*)N_ND->SerRead);
  291.     }
  292.     WaitIO((struct IORequest*)N_ND->SerRead); // to tidy up..
  293.     N_ND->SerWaiting=FALSE;
  294.   }
  295. }
  296.  
  297. // SendIO()'s a request to read 1 bye
  298.  
  299. void __asm __saveds LIBSendSerReadData( void )
  300. {
  301.   N_ND->SerRead->IOSer.io_Command  = CMD_READ;
  302.   N_ND->SerRead->IOSer.io_Data     = (APTR)N_ND->SerBuffer;
  303.   N_ND->SerRead->IOSer.io_Length   = 1;
  304.  
  305.   ClrSignal(1L << N_ND->SerPort->mp_SigBit);
  306.   SendIO((struct IORequest*)N_ND->SerRead);
  307.   N_ND->SerWaiting=TRUE;
  308. }
  309.  
  310. void __asm __saveds LIBSerWaitData( void )
  311. {
  312.   if (!N_ND->SerWaiting) LIBSendSerReadData();
  313.   WaitIO((struct IORequest*)N_ND->SerRead);
  314.   N_ND->SerBytes=N_ND->SerRead->IOSer.io_Actual;
  315.   N_ND->SerWaiting=FALSE;
  316. }
  317.  
  318. // SendIO()'s a request to read a block of data
  319.  
  320. void __asm __saveds LIBSendSerReadBlock(register __a0 UBYTE *data,register __d0 ULONG length )
  321. {
  322.   LIBAbortSerRead(); // *C* not sure about this one..  might slowdown throughput..
  323.  
  324.   N_ND->SerRead->IOSer.io_Command  = CMD_READ;
  325.   N_ND->SerRead->IOSer.io_Data     = (APTR)data;
  326.   N_ND->SerRead->IOSer.io_Length   = length;
  327.  
  328.   ClrSignal(1L << N_ND->SerPort->mp_SigBit);
  329.   SendIO((struct IORequest*)N_ND->SerRead);
  330.   N_ND->SerWaiting=TRUE;
  331. }
  332.  
  333. // DioIO()'s a request to read a block of data
  334.  
  335. void __asm __saveds LIBWaitSerReadBlock(register __a0 UBYTE *data,register __d0 ULONG length )
  336. {
  337.   LIBSendSerReadBlock(data,length);
  338.   LIBSerWaitData();
  339. }
  340.  
  341. // DoIO()'s a Query!
  342.  
  343. ULONG __asm __saveds LIBSerQueryData( void )
  344. {
  345.   N_ND->SerWrite->IOSer.io_Command  = SDCMD_QUERY;
  346.   DoIO((struct IORequest*)N_ND->SerWrite);
  347.   return(N_ND->SerWrite->IOSer.io_Actual);
  348. }
  349.  
  350. V_BOOL __asm __saveds LIBCarrierLost( void )
  351. {
  352.   if (N_ND->LoginType==LOGIN_REMOTE && !N_ND->NodeDevice.NullModemCable)
  353.   {
  354.     LIBSerQueryData();
  355.     return((N_ND->SerWrite->io_Status & 1L << CIAB_COMCD) ? (V_BOOL)TRUE : (V_BOOL)FALSE);
  356.   }
  357.   else return((V_BOOL)FALSE);
  358. }
  359.  
  360. // writes a block of data to the serial port, checking for a timeout
  361. // (specified in seconds,micros) and returns FALSE if a timeout occured before all
  362. // the data has been sent, or there was a memory error.
  363.  
  364. BOOL __asm __saveds LIBSerWriteDataWithTimeout(register __a0 UBYTE *data,register __d0 ULONG length,register __d1 ULONG Seconds,register __d2 ULONG Micros)
  365. {
  366.   BOOL retval=FALSE;
  367.   struct TimerData *TD;
  368.  
  369.   if (TD=SubmitTimer(N_ND->NodeTimer,Seconds,Micros))
  370.   {
  371.     if (data && length>0)
  372.     {
  373.       LIBAbortSerRead();
  374.       N_ND->SerWrite->IOSer.io_Command  = CMD_WRITE;
  375.       N_ND->SerWrite->IOSer.io_Data     = data;
  376.       N_ND->SerWrite->IOSer.io_Length   = length;
  377.  
  378.       SendIO((struct IORequest *)N_ND->SerWrite);
  379.  
  380.       // ok, wait for the timer or serial device to tell us sommat..
  381.       Wait (DEF_TIMERSIG | DEF_SERSIG);
  382.  
  383.       // ok sommat hapenned. lets check the timer..
  384.       if (CheckTimer(N_ND->NodeTimer,TD))
  385.       {
  386.         // yup, timeout occured, so abort the serial write request..
  387.         AbortIO((struct IORequest *)N_ND->SerWrite);
  388.         TD=NULL;
  389.       }
  390.       else
  391.       {
  392.         // timer not done yet, so it must be the serial port that finished..
  393.         retval=TRUE;
  394.       }
  395.       // and then tidy up..
  396.       WaitIO((struct IORequest *)N_ND->SerWrite);
  397.     }
  398.     if (TD) AbortTimer(N_ND->NodeTimer,TD);
  399.   }
  400.   return(retval);
  401. }
  402.  
  403. // writes a block of data to the serial port without checking for a timeout..
  404.  
  405. void __asm __saveds LIBSerWriteData(register __a0 UBYTE *data,register __d0 ULONG length)
  406. {
  407.   if (data && length>0)
  408.   {
  409.     LIBAbortSerRead();
  410.     N_ND->SerWrite->IOSer.io_Command  = CMD_WRITE;
  411.     N_ND->SerWrite->IOSer.io_Data     = data;
  412.     N_ND->SerWrite->IOSer.io_Length   = length;
  413.  
  414.     DoIO((struct IORequest *)N_ND->SerWrite);
  415.   }
  416. }
  417.  
  418. BOOL __asm __saveds LIBSerWriteStrWithTimeout(register __a0 UBYTE *str,register __d0 ULONG Seconds,register __d1 ULONG Micros)
  419. {
  420.   BOOL retval=FALSE;
  421.   struct TimerData *TD;
  422.  
  423.   if (TD=SubmitTimer(N_ND->NodeTimer,Seconds,Micros))
  424.   {
  425.     if (str && str[0])  // str valid pointer ? and does it contain data ??
  426.     {
  427.       LIBAbortSerRead();
  428.       N_ND->SerWrite->IOSer.io_Command  = CMD_WRITE;
  429.       N_ND->SerWrite->IOSer.io_Data     = str;
  430.       N_ND->SerWrite->IOSer.io_Length   = -1;
  431.  
  432.       ClrSignal(DEF_TIMERSIG | DEF_SERSIG);
  433.  
  434.       SendIO((struct IORequest *)N_ND->SerWrite);
  435.  
  436.       // ok, wait for the timer or serial device to tell us sommat..
  437.       Wait (DEF_TIMERSIG | DEF_SERSIG);
  438.  
  439.       // ok sommat hapenned. lets check the timer..
  440.       if (CheckTimer(N_ND->NodeTimer,TD))
  441.       {
  442.         TD=NULL;
  443.         // yup, timeout occured, so abort the serial write request..
  444.         AbortIO((struct IORequest *)N_ND->SerWrite);
  445.       }
  446.       else
  447.       {
  448.         // timer not done yet, so it must be the serial port that finished..
  449.         retval=TRUE;
  450.         // and then tidy up..
  451.       }
  452.       WaitIO((struct IORequest *)N_ND->SerWrite);
  453.     }
  454.     if (TD) AbortTimer(N_ND->NodeTimer,TD);
  455.   }
  456.   return(retval);
  457. }
  458.  
  459. // writes a string to the serial device..
  460.  
  461. void __asm __saveds LIBSerWriteStr(register __a0 UBYTE *str)
  462. {
  463.   if (str && str[0])   // str valid pointer ? and does it contain data ??
  464.   {
  465.     LIBAbortSerRead();
  466.     N_ND->SerWrite->IOSer.io_Command  = CMD_WRITE;
  467.     N_ND->SerWrite->IOSer.io_Data     = str;
  468.     N_ND->SerWrite->IOSer.io_Length   = -1;
  469.     // hehe LamiExpress sets io_Length to strlen(str).. LAME! ;-)
  470.     // if they read the docs they might see that setting io_Length to -1
  471.     // makes the device output the contents of io_Data until it encounters
  472.     // a null terminator! :-)
  473.  
  474.     DoIO((struct IORequest *)N_ND->SerWrite);
  475.   }
  476. }
  477.  
  478. // writes a char to the serial device..
  479.  
  480. void __asm __saveds LIBSerWriteChar(register __d0 UBYTE c)
  481. {
  482.   char ch=c;
  483.  
  484.   LIBAbortSerRead();
  485.   N_ND->SerWrite->IOSer.io_Command  = CMD_WRITE;
  486.   N_ND->SerWrite->IOSer.io_Data     = &ch;
  487.   N_ND->SerWrite->IOSer.io_Length   = 1;
  488.   DoIO((struct IORequest *)N_ND->SerWrite);
  489. }
  490.  
  491. void  __asm __saveds LIBPutText(register __a0 UBYTE *str)
  492. {
  493.   // generic routine for all tring output, this determines wether or not
  494.   // to write to the console or serial ports..
  495.  
  496.   if (N_ND->ConOK) LIBConWriteStr(str);
  497.   if ((N_ND->LoginType==LOGIN_REMOTE) && (!(N_ND->NodeFlags & NFLG_BLOCKSERIAL))) LIBSerWriteStr(str);
  498. }
  499.  
  500. void  __asm __saveds LIBPutData(register __a0 UBYTE *data,register __d0 ULONG Length)
  501. {
  502.   // generic routine for all tring output, this determines wether or not
  503.   // to write to the console or serial ports..
  504.  
  505.   if (N_ND->ConOK) LIBConWriteData(data,Length);
  506.   if ((N_ND->LoginType==LOGIN_REMOTE)  && (!(N_ND->NodeFlags & NFLG_BLOCKSERIAL))) LIBSerWriteData(data,Length);
  507. }
  508.  
  509. void  __asm __saveds LIBPutChar(register __d0 UBYTE ch)
  510. {
  511.   char c=ch;
  512.   // generic routine for all tring output, this determines wether or not
  513.   // to write to the console or serial ports..
  514.   if (N_ND->ConOK) LIBConWriteData(&c,1);
  515.   if ((N_ND->LoginType==LOGIN_REMOTE) && (!(N_ND->NodeFlags & NFLG_BLOCKSERIAL))) LIBSerWriteData(&c,1);
  516. }
  517.  
  518. void  __asm __saveds LIBPutConText(register __a0 UBYTE *str)
  519. {
  520.   // generic routine for all tring output, this determines wether or not
  521.   // to write to the console or serial ports..
  522.  
  523.   if (N_ND->ConOK) LIBConWriteStr(str);
  524. }
  525.  
  526. void  __asm __saveds LIBPutConData(register __a0 UBYTE *data,register __d0 ULONG Length)
  527. {
  528.   // generic routine for all tring output, this determines wether or not
  529.   // to write to the console or serial ports..
  530.  
  531.   if (N_ND->ConOK) LIBConWriteData(data,Length);
  532. }
  533.  
  534. void  __asm __saveds LIBPutConChar(register __d0 UBYTE ch)
  535. {
  536.   char c=ch;
  537.   // generic routine for all tring output, this determines wether or not
  538.   // to write to the console or serial ports..
  539.   if (N_ND->ConOK) LIBConWriteData(&c,1);
  540. }
  541.  
  542. ULONG __asm __saveds LIBSetupConSerSigs( void )
  543. {
  544.   N_ND->ConSig=0L;
  545.   N_ND->ConWinSig=0L;
  546.   if (N_ND->ConOK)
  547.   {
  548.     if (N_ND->ConWaiting) N_ND->ConSig=DEF_CONSIG;
  549.     N_ND->ConWinSig=DEF_CONWINSIG;
  550.   }
  551.  
  552.   // only check serial if remote login.. OR if no-one's connected yet..
  553.  
  554.   if (N_ND->LoginType !=LOGIN_LOCAL && N_ND->SerOK && N_ND->SerWaiting)
  555.     N_ND->SerSig=DEF_SERSIG;
  556.   else
  557.     N_ND->SerSig=0;
  558.  
  559.   return(N_ND->SerSig | N_ND->ConSig);
  560. }
  561.  
  562. ULONG __asm __saveds LIBHandleConSigs(register __d0 ULONG ReturnedSigs)
  563. {
  564.   // a calling routine should call this until it returns false
  565.   // this is cos you might get two signals at the same time
  566.   // and you don't want to miss anything!
  567.  
  568.   if (ReturnedSigs & N_ND->ConSig && N_ND->ConOK && N_ND->ConWaiting)
  569.   {
  570.     LIBConWaitData();
  571.     N_ND->IBuffer=N_ND->ConBuffer;
  572.     N_ND->IBytes=N_ND->ConBytes;
  573.     return(TRUE);
  574.   }
  575.   return(FALSE);
  576. }
  577.  
  578. ULONG __asm __saveds LIBHandleSerSigs(register __d0 ULONG ReturnedSigs)
  579. {
  580.   // a calling routine should call this until it returns false
  581.   // this is cos you might get two signals at the same time
  582.   // and you don't want to miss anything!
  583.  
  584.  
  585.   if (ReturnedSigs & N_ND->SerSig && N_ND->SerOK && N_ND->SerWaiting)
  586.   {
  587.     LIBSerWaitData();
  588.     N_ND->IBuffer=N_ND->SerBuffer;
  589.     N_ND->IBytes=N_ND->SerBytes;
  590.     return(TRUE);
  591.   }
  592.   return(FALSE);
  593. }
  594.  
  595. ULONG __asm __saveds LIBHandleConSerSigs(register __d0 ULONG ReturnedSigs)
  596. {
  597.   // a calling routine should call this until it returns false
  598.   // this is cos you might get two signals at the same time
  599.   // and you don't want to miss anything!
  600.  
  601.   if (LIBHandleConSigs(ReturnedSigs) || LIBHandleSerSigs(ReturnedSigs))
  602.   {
  603.     return(TRUE);
  604.   }
  605.   else return(FALSE);
  606.  
  607. /*  if (ReturnedSigs & N_ND->ConSig && N_ND->ConOK && N_ND->ConWaiting)
  608.   {
  609.     LIBConWaitData();
  610.     N_ND->IBuffer=N_ND->ConBuffer;
  611.     N_ND->IBytes=N_ND->ConBytes;
  612.     return(TRUE);
  613.   }
  614.  
  615.   if (ReturnedSigs & N_ND->SerSig && N_ND->SerOK && N_ND->SerWaiting)
  616.   {
  617.     LIBSerWaitData();
  618.     N_ND->IBuffer=N_ND->SerBuffer;
  619.     N_ND->IBytes=N_ND->SerBytes;
  620.     return(TRUE);
  621.   }
  622.   return(FALSE);
  623. */
  624. }
  625.  
  626. ULONG SendDoorIOMessage(ULONG Status,UBYTE *Data,ULONG DataLength,ULONG Flags,UBYTE *OptionStr,ULONG Num1,ULONG Num2)
  627. {
  628.   ULONG retval=0;
  629.   struct DoorIOMsg *NewIOMsg=NULL;
  630.   if (NewIOMsg=(struct DoorIOMsg*)AllocVec(sizeof(struct DoorIOMsg),MEMF_PUBLIC))
  631.   {
  632.     NewIOMsg->message.mn_Node.ln_Type = NT_MESSAGE;
  633.     NewIOMsg->message.mn_ReplyPort=C_DOOR.ReplyPort;
  634.     NewIOMsg->message.mn_Length=sizeof(struct DoorIOMsg);
  635.     NewIOMsg->MsgType=mtype_DOORIO;
  636.     NewIOMsg->Status=Status;
  637.     NewIOMsg->Data=Data;
  638.     NewIOMsg->DataLength=DataLength;
  639.     NewIOMsg->ReturnVal=0;
  640.     NewIOMsg->Flags=Flags;
  641.     NewIOMsg->OptionStr=OptionStr;
  642.     NewIOMsg->Num1=Num1;
  643.     NewIOMsg->Num2=Num2;
  644.     SendMessage((struct Message*)NewIOMsg,N_ND->PortName);
  645.     retval=NewIOMsg->ReturnVal;
  646.     FreeVec(NewIOMsg);
  647.   }
  648.   return(retval);
  649. }
  650.  
  651. void __asm __saveds LIBDOOR_SysopText(register __a0 UBYTE *str)
  652. {
  653.   SendDoorIOMessage(DOORIO_WRITECONSTR,str,0,0,NULL,0,0);
  654. }
  655.  
  656. void __asm __saveds LIBDOOR_WriteText(register __a0 UBYTE *str)
  657. {
  658.   SendDoorIOMessage(DOORIO_WRITESTR,str,0,0,NULL,0,0);
  659. }
  660.  
  661. void __asm __saveds LIBDOOR_WriteSerText(register __a0 UBYTE *str)
  662. {
  663.   SendDoorIOMessage(DOORIO_WRITESERSTR,str,0,0,NULL,0,0);
  664. }
  665.  
  666. ULONG __asm __saveds LIBDOOR_GetLine(register __d0 ULONG Flags, register __d1 char PasswordChar,register __d2 ULONG MaxLen,register __d3 ULONG Timeout,register __a0 UBYTE *PromptStr)
  667. {
  668.   char c=PasswordChar;
  669.  
  670.   return(SendDoorIOMessage(DOORIO_GETLINE,&c,1,Flags,PromptStr,MaxLen,Timeout));
  671. }
  672.  
  673. void __asm __saveds LIBDOOR_UpdateNodeStatus(register __d0 ULONG What)
  674. {
  675.   UBYTE *str=NULL;
  676.   UWORD X=0,MaxLen;
  677.   switch(What)
  678.   {
  679.     case UPD_NAME:
  680.       if (N_ND->User.Valid) str=N_ND->User.NormalData.Handle;
  681.       X=4;
  682.       MaxLen=MAX_NAME_LEN;
  683.       break;
  684.     case UPD_GROUP:
  685.       if (N_ND->User.Valid) str=N_ND->User.NormalData.Group;
  686.       X=164;
  687.       MaxLen=MAX_GROUP_LEN;
  688.       break;
  689.     case UPD_ACTION:
  690.       str=N_ND->Action;
  691.       X=324;
  692.       MaxLen=MAX_ACTION_LEN;
  693.       break;
  694.     case UPD_CPSBAUD:
  695.       if (!N_ND->TransferringFile) str=N_ND->ConnectBaud; // *C* add cps here
  696.       X=556;
  697.       MaxLen=MAX_CPSBAUD_LEN;
  698.     default:
  699.       return;
  700.   }
  701.   // ok, have we got an option ?
  702.   // and a string to print ?
  703.   // AND if the window open ?
  704.   if ((X) && (str) && (!N_ND->NodeSettings.Iconified))
  705.   {
  706.     SetAPen(N_ND->NodeWnd->RPort,0L); // 0=grey
  707.     SetBPen(N_ND->NodeWnd->RPort,0); // grey!
  708.     RectFill(N_ND->NodeWnd->RPort, X+N_ND->NodeWnd->BorderLeft,15+N_ND->NodeWnd->BorderTop,X+N_ND->NodeWnd->BorderLeft+(8*MaxLen),15+N_ND->NodeWnd->BorderTop+9);
  709.  
  710.     if ((What == UPD_NAME) && (N_ND->NodeFlags & NFLG_PAGED))
  711.     {
  712.       SetAPen(N_ND->NodeWnd->RPort,2L); // white!
  713.     }
  714.     else
  715.     {
  716.       SetAPen(N_ND->NodeWnd->RPort,1L); // black!
  717.     }
  718.     Move(N_ND->NodeWnd->RPort,1+X+N_ND->NodeWnd->BorderLeft,8+14+N_ND->NodeWnd->BorderTop);  // 8 for text height, 13 for placement
  719.     Text(N_ND->NodeWnd->RPort,str,(strlen(str)>MaxLen) ? MaxLen : strlen(str));
  720.   }
  721. }
  722.  
  723. // spawn another system door, e.g. "FRONTEND"
  724.  
  725. void __asm __saveds LIBDOOR_SystemDoor(register __a0 UBYTE *doorname,register __a1 UBYTE *options)
  726. {
  727.   SendDoorIOMessage(DOORIO_SYSTEMDOOR,doorname,0,0,options,0,0);
  728. }
  729.  
  730. // spawn another user door, e.g. "FR W"
  731.  
  732. V_BOOL __asm __saveds LIBDOOR_UserDoor(register __a0 UBYTE *doorname,register __a1 UBYTE *options)
  733. {
  734.   return(SendDoorIOMessage(DOORIO_USERDOOR,doorname,0,0,options,0,0));
  735. }
  736.  
  737. V_BOOL __asm __saveds LIBDOOR_HangUp( void )
  738. {
  739.   return(SendDoorIOMessage(DOORIO_HANGUP,NULL,0,0,NULL,0,0));
  740. }
  741.  
  742. void __asm __saveds LIBDOOR_Return( register __a0 UBYTE *returnstring )
  743. {
  744.   strNcpy(N_ND->DoorReturn,returnstring,LEN_MAXDOORRETURN);
  745. }
  746.  
  747. V_BOOL __asm __saveds LIBDOOR_DisplayScreen( register __a0 UBYTE *screenname )
  748. {
  749.   return(SendDoorIOMessage(DOORIO_DISPLAYSCREEN,screenname,0,0,NULL,0,0));
  750. }
  751.  
  752. V_BOOL __asm __saveds LIBDOOR_DisplaySpecialScreen( register __a0 UBYTE *screenname )
  753. {
  754.   return(SendDoorIOMessage(DOORIO_DISPLAYSPECIALSCREEN,screenname,0,0,NULL,0,0));
  755. }
  756.  
  757.  
  758. V_BOOL __asm __saveds LIBDOOR_PausePrompt( register __a0 UBYTE *prompt )
  759. {
  760.   return(SendDoorIOMessage(DOORIO_PAUSEPROMPT,prompt,0,0,NULL,0,0));
  761. }
  762.  
  763. void __asm __saveds LIBDOOR_Add_Last_Upload( register __a0 UBYTE *details )
  764. {
  765.   SendDoorIOMessage(DOORIO_ADDLASTUPLOAD,details,0,0,NULL,0,0);
  766. }
  767.  
  768.  
  769.  
  770. V_BOOL __asm __saveds LIBDOOR_ContinuePrompt( register __a0 UBYTE *prompt,register __d0 V_BIGNUM Flags )
  771. {
  772.   return(SendDoorIOMessage(DOORIO_CONTINUEPROMPT,prompt,0,Flags,NULL,0,0));
  773. }
  774.  
  775.  
  776. void __asm __saveds LIBDOOR_MenuPrompt(register __a0 char *promptstr,register __d0 char promptdefault)
  777. {
  778.   char options[2];
  779.   options[0]=promptdefault;
  780.   options[1]=0;
  781.  
  782.   SendDoorIOMessage(DOORIO_MENUPROMPT,promptstr,0,0,options,0,0);
  783. }
  784.  
  785. void __asm __saveds LIBDOOR_Continue( register __d0 V_BOOL Continue )
  786. {
  787.   N_ND->DoorContinue=Continue;
  788. }
  789.  
  790. V_BOOL __asm __saveds LIBValidConfNum(register __d0 V_BIGNUM ConfNum)
  791. {
  792.   // index from 1 (i.e. first conf = 1
  793.   return((V_BOOL)((ConfNum>0 && ConfNum <=BBSGlobal->Conferences) ? TRUE : FALSE));
  794. }
  795.  
  796. struct ConfData __asm __saveds *LIBFindConf( void )
  797. {
  798.   struct ConfData *Conf=NULL;
  799.   V_BIGNUM ConfNum;
  800.  
  801.  
  802.   if (N_ND->CurrentConf)
  803.   {
  804.     Conf=N_ND->CurrentConf;
  805.   }
  806.   else
  807.   {
  808.     if (N_ND->User.Valid)
  809.     {
  810.       if (ConfNum=N_ND->User.CallData.LastConf)
  811.       {
  812.         if (LIBValidConfNum(ConfNum))
  813.         {
  814.           Conf=(struct ConfData *)GetNode(BBSGlobal->ConfList,ConfNum-1);
  815.         }
  816.       }
  817.     }
  818.   }
  819.   return(Conf);
  820.  
  821. }
  822.  
  823.  
  824. void  __asm __saveds LIBLoadAccess( register __a0 char *filename, register __a1 struct AccessData *AD)
  825. {
  826.   struct CfgFileData *CfgFile;
  827.   V_BOOL acsdata;
  828.  
  829.   if (CfgFile=HBBS_LoadConfig(filename,LCFG_NONE))
  830.   {
  831.  
  832.     /* Main Options */
  833.  
  834.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_DLFILES,OPT_SINGLE))
  835.       AD->Data[ACS_DLFILES]=acsdata ? 'Y' : 'N';
  836.  
  837.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_ULFILES,OPT_SINGLE))
  838.       AD->Data[ACS_ULFILES]=acsdata ? 'Y' : 'N';
  839.  
  840.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_SYSOPCOMMENT,OPT_SINGLE))
  841.       AD->Data[ACS_SYSOPCOMMENT]=acsdata ? 'Y' : 'N';
  842.  
  843.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_READMAIL,OPT_SINGLE))
  844.       AD->Data[ACS_READMAIL]=acsdata ? 'Y' : 'N';
  845.  
  846.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_WRITEMAIL,OPT_SINGLE))
  847.       AD->Data[ACS_WRITEMAIL]=acsdata ? 'Y' : 'N';
  848.  
  849.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_SCANMAIL,OPT_SINGLE))
  850.       AD->Data[ACS_SCANMAIL]=acsdata ? 'Y' : 'N';
  851.  
  852.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_ALLOWSTATUS,OPT_SINGLE))
  853.       AD->Data[ACS_ALLOWSTATUS]=acsdata ? 'Y' : 'N';
  854.  
  855.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_ALLOWEDIT,OPT_SINGLE))
  856.       AD->Data[ACS_ALLOWEDIT]=acsdata ? 'Y' : 'N';
  857.  
  858.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_SCANFILES,OPT_SINGLE))
  859.       AD->Data[ACS_SCANFILES]=acsdata ? 'Y' : 'N';
  860.  
  861.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_ALLOWVIEW,OPT_SINGLE))
  862.       AD->Data[ACS_ALLOWVIEW]=acsdata ? 'Y' : 'N';
  863.  
  864.  
  865.     /* Mail Options */
  866.  
  867.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_DELETEMAIL,OPT_SINGLE))
  868.       AD->Data[ACS_DELETEMAIL]=acsdata ? 'Y' : 'N';
  869.  
  870.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_DELETEGROUP,OPT_SINGLE))
  871.       AD->Data[ACS_DELETEGROUP]=acsdata ? 'Y' : 'N';
  872.  
  873.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_DELETEANYONE,OPT_SINGLE))
  874.       AD->Data[ACS_DELETEANYONE]=acsdata ? 'Y' : 'N';
  875.  
  876.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_ALLOWALL,OPT_SINGLE))
  877.       AD->Data[ACS_ALLOWALL]=acsdata ? 'Y' : 'N';
  878.  
  879.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_ALLOWEVERYBODY,OPT_SINGLE))
  880.       AD->Data[ACS_ALLOWEVERYBODY]=acsdata ? 'Y' : 'N';
  881.  
  882.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_ALLOWMULTIPLE,OPT_SINGLE))
  883.       AD->Data[ACS_ALLOWMULTIPLE]=acsdata ? 'Y' : 'N';
  884.  
  885.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_ATTACHFILES,OPT_SINGLE))
  886.       AD->Data[ACS_ATTACHFILES]=acsdata ? 'Y' : 'N';
  887.  
  888.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_ALLOWMULTIFILES,OPT_SINGLE))
  889.       AD->Data[ACS_ALLOWMULTIFILES]=acsdata ? 'Y' : 'N';
  890.  
  891.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_ALLOWPRIVATEFILES,OPT_SINGLE))
  892.       AD->Data[ACS_ALLOWPRIVATEFILES]=acsdata ? 'Y' : 'N';
  893.  
  894.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_ALLOWALLFILES,OPT_SINGLE))
  895.       AD->Data[ACS_ALLOWALLFILES]=acsdata ? 'Y' : 'N';
  896.  
  897.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_ALLOWEVERYONEFILES,OPT_SINGLE))
  898.       AD->Data[ACS_ALLOWEVERYONEFILES]=acsdata ? 'Y' : 'N';
  899.  
  900.     /* W command settings */
  901.  
  902.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_EDITHANDLE,OPT_SINGLE))
  903.       AD->Data[ACS_EDITHANDLE]=acsdata ? 'Y' : 'N';
  904.  
  905.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_EDITREALNAME,OPT_SINGLE))
  906.       AD->Data[ACS_EDITREALNAME]=acsdata ? 'Y' : 'N';
  907.  
  908.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_EDITPASSWORD,OPT_SINGLE))
  909.       AD->Data[ACS_EDITPASSWORD]=acsdata ? 'Y' : 'N';
  910.  
  911.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_EDITGROUP,OPT_SINGLE))
  912.       AD->Data[ACS_EDITGROUP]=acsdata ? 'Y' : 'N';
  913.  
  914.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_EDITLOCATION,OPT_SINGLE))
  915.       AD->Data[ACS_EDITLOCATION]=acsdata ? 'Y' : 'N';
  916.  
  917.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_EDITCOUNTRY,OPT_SINGLE))
  918.       AD->Data[ACS_EDITCOUNTRY]=acsdata ? 'Y' : 'N';
  919.  
  920.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_EDITCOMPUTER,OPT_SINGLE))
  921.       AD->Data[ACS_EDITCOMPUTER]=acsdata ? 'Y' : 'N';
  922.  
  923.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_EDITPHONENUMBER,OPT_SINGLE))
  924.       AD->Data[ACS_EDITPHONENUMBER]=acsdata ? 'Y' : 'N';
  925.  
  926.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_EDITSCREENTYPE,OPT_SINGLE))
  927.       AD->Data[ACS_EDITSCREENTYPE]=acsdata ? 'Y' : 'N';
  928.  
  929.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_EDITLINES,OPT_SINGLE))
  930.       AD->Data[ACS_EDITLINES]=acsdata ? 'Y' : 'N';
  931.  
  932.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_EDITEDITOR,OPT_SINGLE))
  933.       AD->Data[ACS_EDITEDITOR]=acsdata ? 'Y' : 'N';
  934.  
  935.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_EDITPROTOCOL,OPT_SINGLE))
  936.       AD->Data[ACS_EDITPROTOCOL]=acsdata ? 'Y' : 'N';
  937.  
  938.  
  939. /*  Spare ones
  940.  
  941.  
  942.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_,OPT_SINGLE))
  943.       AD->Data[ACS_]=acsdata ? 'Y' : 'N';
  944.  
  945.     if (HBBS_GetSetting(CfgFile,(void *)&acsdata,VTYPE_BOOL,ACSSTR_,OPT_SINGLE))
  946.       AD->Data[ACS_]=acsdata ? 'Y' : 'N';
  947. */
  948.     HBBS_FlushConfig(CfgFile);
  949.   }
  950.  
  951. }
  952.  
  953.  
  954. char __asm __saveds *LIBHBBS_ModifyString(register __a0 char *str)
  955. {
  956.   char tmpstr[20];  // *D* Document! the {x} codes
  957.  
  958.   // Time Left
  959.  
  960.   sprintf(tmpstr,"%d",N_ND->User.CallData.TimeAllowed-N_ND->User.CallData.TimeUsed);
  961.   replace(str,str,"{L}",tmpstr);
  962.  
  963.   // System Name
  964.  
  965.   replace(str,str,"{S}",BBSGlobal->BBSName);
  966.  
  967.   // Conference Name
  968.  
  969.   if (N_ND->CurrentConf) replace(str,str,"{C}",N_ND->CurrentConf->node.ln_Name);
  970.  
  971.   // Actual Time Without Seconds
  972.  
  973.   HBBS_GetTime(tmpstr);
  974.   tmpstr[5]=0;
  975.   replace(str,str,"{T}",tmpstr);
  976.  
  977.   // Actual Time WITH seconds
  978.  
  979.   HBBS_GetTime(tmpstr);
  980.   replace(str,str,"{TS}",tmpstr);
  981.  
  982.   // Actual Date
  983.  
  984.   HBBS_GetDate(tmpstr);
  985.   replace(str,str,"{D}",tmpstr);
  986.  
  987.   // Credits Left (In Current Conference)
  988.  
  989.   replace(str,str,"{B}","<Creds>");
  990.  
  991.   // Ansi CSI
  992.  
  993.   replace(str,str,"{E}","\033[");
  994.  
  995.  
  996.   if (N_ND->User.Valid)
  997.   {
  998.  
  999.     // Users Handle
  1000.  
  1001.     replace(str,str,"{H}",N_ND->User.CallData.Handle);
  1002.  
  1003.     // Users Group
  1004.  
  1005.     replace(str,str,"{G}",N_ND->User.CallData.Group);
  1006.   }
  1007.  
  1008.   return(str);
  1009. }
  1010.  
  1011. void __asm __saveds LIBHBBS_SetAccess( void )
  1012. {
  1013.   char tmpfilename[1024];
  1014.   V_BIGNUM loop;
  1015.  
  1016.   // Clear out the access
  1017.  
  1018.   for (loop=0;loop<MAX_ACCESSSETTINGS;loop++)
  1019.   {
  1020.     N_ND->User.Acs.Data[loop]='N';
  1021.   }
  1022.  
  1023.   if (N_ND->User.Valid)
  1024.   {
  1025.     N_ND->User.Acs.AccessLevel=N_ND->User.CallData.Access;
  1026.  
  1027.     LIBLoadAccess("HBBS:Access/Levels/Level_Global",&N_ND->User.Acs);
  1028.  
  1029.     sprintf(tmpfilename,"HBBS:Access/Levels/Level_%d",N_ND->User.Acs.AccessLevel);
  1030.     LIBLoadAccess(tmpfilename,&N_ND->User.Acs);
  1031.  
  1032.     sprintf(tmpfilename,"%sAccess/Level_%d",N_ND->NodeLocation,N_ND->User.Acs.AccessLevel);
  1033.     LIBLoadAccess(tmpfilename,&N_ND->User.Acs);
  1034.  
  1035.     if (N_ND->CurrentConf)
  1036.     {
  1037.       sprintf(tmpfilename,"%sAccess/Level_%d",N_ND->CurrentConf->ConfPath,N_ND->User.Acs.AccessLevel);
  1038.       LIBLoadAccess(tmpfilename,&N_ND->User.Acs);
  1039.     }
  1040.  
  1041.     sprintf(tmpfilename,"HBBS:Access/Users/%s",N_ND->User.CallData.Handle);
  1042.     LIBLoadAccess(tmpfilename,&N_ND->User.Acs);
  1043.  
  1044.   }
  1045. }
  1046.  
  1047. V_BOOL __asm __saveds LIBHBBS_CheckAccess(register __d0 ULONG AccessOption)
  1048. {
  1049.   if ((N_ND->User.Valid) && (N_ND->User.Acs.Data[AccessOption]=='Y')) return(TRUE); else return(FALSE);
  1050. }
  1051.  
  1052. void __asm __saveds LIBHBBS_AddToCallersLog(register __a0 UBYTE *String)
  1053. {
  1054.   UBYTE tmpstr[BIG_STR];
  1055.  
  1056.   if (N_ND->NodeSettings.CallersLogFile)
  1057.   {
  1058.  
  1059.     HBBS_GetDate(tmpstr);
  1060.     strcat(tmpstr," ");
  1061.     HBBS_GetTime(tmpstr+strlen(tmpstr));
  1062.     strcat(tmpstr," ");
  1063.     strcat(tmpstr,String);
  1064.     strcat(tmpstr,"\n");
  1065.  
  1066.     HBBS_AppendStrToFile(N_ND->NodeSettings.CallersLogFile,tmpstr);
  1067.   }
  1068. }
  1069.  
  1070.  
  1071. struct TaggedFile __asm __saveds *LIBHBBS_FindTag(register __a0 UBYTE *FileName,register __d0 BOOL MatchALL)
  1072. {
  1073.   struct TaggedFile *Tag=NULL,*retval=NULL;
  1074.  
  1075.   if (N_ND->TaggedFiles)
  1076.   {
  1077.     for (Tag=(struct TaggedFile*)N_ND->TaggedFileList->lh_Head;!retval && Tag->node.ln_Succ;Tag=(struct TaggedFile *)Tag->node.ln_Succ)
  1078.     {
  1079.       if (MatchALL)
  1080.       {
  1081.         if (stricmp(FileName,Tag->node.ln_Name)==0)
  1082.         {
  1083.           retval=Tag;
  1084.         }
  1085.       }
  1086.       else
  1087.       {
  1088.         if (stricmp(FilePart(FileName),FilePart(Tag->node.ln_Name))==0)
  1089.         {
  1090.           retval=Tag;
  1091.         }
  1092.       }
  1093.     }
  1094.   }
  1095.   return(retval);
  1096. }
  1097.  
  1098.  
  1099. void __asm __saveds LIBHBBS_SetBBSCols( void )
  1100. {
  1101.   struct CfgFileData *CfgFile;
  1102.   char filename[1024],*bbscolsfile="BBSColours.CFG";
  1103.  
  1104.   BOOL foundfile=FALSE;
  1105.   BYTE triedall=3;
  1106.  
  1107.   FreeAndSet(&N_ND->BBSCols->MenuTextANSI,"");
  1108.   FreeAndSet(&N_ND->BBSCols->MenuOpenBracket,"[");
  1109.   FreeAndSet(&N_ND->BBSCols->MenuCloseBracket,"]");
  1110.   FreeAndSet(&N_ND->BBSCols->MenuHighlightANSI,"");
  1111.   FreeAndSet(&N_ND->BBSCols->MenuDefaultOptANSI,"");
  1112.   FreeAndSet(&N_ND->BBSCols->MenuPromptANSI,":");
  1113.  
  1114.   do
  1115.   {
  1116.     triedall--;
  1117.     switch (triedall)
  1118.     {
  1119.       case 2:
  1120.         if (N_ND->CurrentConf)
  1121.         {
  1122.           strcpy(filename,N_ND->CurrentConf->ConfPath);
  1123.           strcat(filename,bbscolsfile);
  1124.         } else filename[0]=0;
  1125.         break;
  1126.       case 1:
  1127.         strcpy(filename,N_ND->NodeLocation);
  1128.         strcat(filename,bbscolsfile);
  1129.         break;
  1130.       case 0:
  1131.         strcpy(filename,"HBBS:System/Data/");
  1132.         strcat(filename,bbscolsfile);
  1133.         break;
  1134.     }
  1135.     if (filename[0])
  1136.     {
  1137.       if (CfgFile=HBBS_LoadConfig(filename,LCFG_NOSTRIPCOMMENTS))
  1138.       {
  1139.         foundfile=TRUE;
  1140.         HBBS_GetSetting(CfgFile,(void *)&N_ND->BBSCols->MenuTextANSI,VTYPE_STRING,"MenuTextANSI",OPT_SINGLE)          ;
  1141.         HBBS_GetSetting(CfgFile,(void *)&N_ND->BBSCols->MenuOpenBracket,VTYPE_STRING,"MenuOpenBracket",OPT_SINGLE)       ;
  1142.         HBBS_GetSetting(CfgFile,(void *)&N_ND->BBSCols->MenuCloseBracket,VTYPE_STRING,"MenuCloseBracket",OPT_SINGLE)     ;
  1143.         HBBS_GetSetting(CfgFile,(void *)&N_ND->BBSCols->MenuHighlightANSI,VTYPE_STRING,"MenuHighlightANSI",OPT_SINGLE)    ;
  1144.         HBBS_GetSetting(CfgFile,(void *)&N_ND->BBSCols->MenuDefaultOptANSI,VTYPE_STRING,"MenuDefaultOptANSI",OPT_SINGLE) ;
  1145.         HBBS_GetSetting(CfgFile,(void *)&N_ND->BBSCols->MenuPromptANSI,VTYPE_STRING,"MenuPromptANSI",OPT_SINGLE)         ;
  1146.  
  1147.         HBBS_FlushConfig(CfgFile);
  1148.       }
  1149.     }
  1150.   } while ((!foundfile) && (triedall>0));
  1151. }
  1152.  
  1153.